/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-01-10     86157       the first version
 */
#include "command_frame.h"

//发送命令帧

//遥控命令帧（固定分组模式） 180180A0
int j1939_GDCMD_FixedGroup(uint8_t addr, uint8_t PDU, uint8_t operation_instructions, uint8_t voltage_output_range)
{
    J1939_MESSAGE _msg;

    set_charging_param(operation_instructions, voltage_output_range);

    /*****发送数据(参考J1939的ID组成填充下面)***/
    _msg.j1939_pid.DataPage = 0;
    _msg.j1939_pid.Priority = J1939_PROPRIETARY_PRIORITY;
    _msg.j1939_pid.PDUSpecific = addr; //PDU1格式下 -- 目标地址
    _msg.j1939_pid.DataLength = 8;     //数据长度   
    _msg.j1939_pid.PDUFormat = PDU;   //指定PDU格式 < 240为 PDU1
    _msg.j1939_pid.Data[0] = (control_info.control_byte.reserved << 7) |
                             (control_info.control_byte.main_contact_status << 6) |
                             (control_info.control_byte.power_distribution_contact_status << 5) |
                             (control_info.control_byte.voltage_output_range << 4) |
                             (control_info.control_byte.operation_instructions);
    _msg.j1939_pid.Data[1] = (control_info.group_byte.eight_group << 7) |
                             (control_info.group_byte.seven_group << 6) |
                             (control_info.group_byte.six_group << 5)   |
                             (control_info.group_byte.fifty_group << 4) |
                             (control_info.group_byte.four_group << 3)  |
                             (control_info.group_byte.three_group << 2) |
                             (control_info.group_byte.two_group << 1)   |
                             (control_info.group_byte.one_group << 0);
    _msg.j1939_pid.Data[2] = control_info.set_vdc & 0xFF;         //存入低八位
    _msg.j1939_pid.Data[3] = (control_info.set_vdc >> 8) & 0xFF;  //存入高八位
    _msg.j1939_pid.Data[4] = control_info.set_current & 0xFF;
    _msg.j1939_pid.Data[5] = (control_info.set_current >> 8) & 0xFF;
    _msg.j1939_pid.Data[6] = control_info.battery_vdc & 0xFF;
    _msg.j1939_pid.Data[7] = (control_info.battery_vdc >> 8) & 0xFF;

    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);
    return SUCCESS;
}


//遥控命令帧（动态分组模式） 180580A0
int j1939_GDCMD_DynamicGroup(uint8_t addr, uint8_t PDU, uint8_t operation_instructions, uint8_t voltage_output_range)
{
    J1939_MESSAGE _msg;

    set_charging_param(operation_instructions, voltage_output_range);

    /*****发送数据(参考J1939的ID组成填充下面)***/
    _msg.j1939_pid.DataPage = 0;
    _msg.j1939_pid.Priority = J1939_PROPRIETARY_PRIORITY;
    _msg.j1939_pid.PDUSpecific = addr; //PDU1格式下 -- 目标地址
    _msg.j1939_pid.DataLength = 8;     //数据长度   
    _msg.j1939_pid.PDUFormat = PDU;   //指定PDU格式 < 240为 PDU1
    _msg.j1939_pid.Data[0] = (control_info.control_byte.reserved << 7) |
                             (control_info.control_byte.main_contact_status << 6) |
                             (control_info.control_byte.power_distribution_contact_status << 5) |
                             (control_info.control_byte.voltage_output_range << 4) |
                             (control_info.control_byte.operation_instructions);
    _msg.j1939_pid.Data[1] = control_info.group_encoding;
    _msg.j1939_pid.Data[2] = control_info.set_vdc & 0xFF;         //存入低八位
    _msg.j1939_pid.Data[3] = (control_info.set_vdc >> 8) & 0xFF;  //存入高八位
    _msg.j1939_pid.Data[4] = control_info.set_current & 0xFF;
    _msg.j1939_pid.Data[5] = (control_info.set_current >> 8) & 0xFF;
    _msg.j1939_pid.Data[6] = control_info.battery_vdc & 0xFF;
    _msg.j1939_pid.Data[7] = (control_info.battery_vdc >> 8) & 0xFF;

    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);
    return SUCCESS;
}

//定值设置命令帧
int j1939_SET_VALUECMD(FixedValueSet *pthis, j1939_uint8_t addr, uint8_t PDU)
{
    J1939_MESSAGE _msg;

    j1939_uint16_t frame_len = FIXED_LEN; //帧长度

    /*****发送数据(参考J1939的ID组成填充下面)***/
    _msg.j1939_pid.DataPage = 0;       //数据页
    _msg.j1939_pid.Priority = J1939_PROPRIETARY_PRIORITY; //优先级6
    _msg.j1939_pid.PDUSpecific = addr; //PDU1格式下 -- 目标地址(充电模块地址)
    _msg.j1939_pid.DataLength = 8;     //数据长度
    _msg.j1939_pid.PDUFormat = PDU;   //指定PDU格式 < 240为 PDU1

    frame_len = pthis->fix_info_len + FIXED_LEN; //帧总长度

    _msg.j1939_pid.Data[0] = format.frame_one;                          //第一帧数据
    _msg.j1939_pid.Data[1] = format.frame_num;                          //共两帧报文
    _msg.j1939_pid.Data[2] = frame_len & 0xFF;                          //有效数据长度低位
    _msg.j1939_pid.Data[3] = (frame_len >> 8) & 0xFF;                   //有效数据长度高位
    _msg.j1939_pid.Data[4] = pthis->charg_flag;                    //充电接口标识
    _msg.j1939_pid.Data[5] = pthis->device_type;                   //设备类型
    _msg.j1939_pid.Data[6] = pthis->address;                       //设备通信地址
    _msg.j1939_pid.Data[7] = pthis->order & 0xFF;                  //定值序号低位
    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);

    rt_thread_mdelay(10);

    //CRC校验和
    format.checksum = _msg.j1939_pid.Data[1] + _msg.j1939_pid.Data[2] + _msg.j1939_pid.Data[3] + _msg.j1939_pid.Data[4] + _msg.j1939_pid.Data[5] + _msg.j1939_pid.Data[6] + _msg.j1939_pid.Data[7];

    _msg.j1939_pid.Data[0] = format.frame_two;                          //第二帧数据
    _msg.j1939_pid.Data[1] = (pthis->order >> 8) & 0xFF;           //定值序号高位
    _msg.j1939_pid.Data[2] = pthis->reserved;                      //预留
   

    if(pthis->fix_info_len == 1)
    {
        _msg.j1939_pid.Data[3] = pthis->fix_info;          //定值信息

        format.checksum += _msg.j1939_pid.Data[1]  + _msg.j1939_pid.Data[3]; //CRC校验和

        _msg.j1939_pid.Data[4] = format.checksum & 0xFF;        //CRC校验低位                    
        _msg.j1939_pid.Data[5] = (format.checksum >> 8) & 0xFF; //CRC校验高位 
        _msg.j1939_pid.Data[6] = 0;
        _msg.j1939_pid.Data[7] = 0;
    }
    else
    {
        _msg.j1939_pid.Data[3] = pthis->fix_info;          //定值信息低位
        _msg.j1939_pid.Data[4] = pthis->fix_info >> 8;     //定值信息高位

        format.checksum += _msg.j1939_pid.Data[1]  + _msg.j1939_pid.Data[3]  + _msg.j1939_pid.Data[4]; //CRC校验和
    
        _msg.j1939_pid.Data[5] = format.checksum & 0xFF;        //CRC校验低位                    
        _msg.j1939_pid.Data[6] = (format.checksum >> 8) & 0xFF; //CRC校验高位 
        _msg.j1939_pid.Data[7] = 0;
    }

    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);

    return SUCCESS;
}

//分组设置命令帧
int j1939_GPCMD_DynamicGroup(GroupSetFrame *pthis, uint8_t addr, uint8_t PDU)
{
    J1939_MESSAGE _msg;

    /*****发送数据(参考J1939的ID组成填充下面)***/
    _msg.j1939_pid.DataPage = 0;
    _msg.j1939_pid.Priority = J1939_PROPRIETARY_PRIORITY;
    _msg.j1939_pid.PDUSpecific = addr; //PDU1格式下 -- 目标地址
    _msg.j1939_pid.DataLength = 8;     //数据长度
    _msg.j1939_pid.PDUFormat = PDU;   //指定PDU格式 < 240为 PDU1
    _msg.j1939_pid.Data[0] = (pthis->cmd_byte.reversed1 << 7) | 
                             (pthis->cmd_byte.group_set_undo << 5) |
                             (pthis->cmd_byte.addr_select << 3) | 
                             (pthis->cmd_byte.reversed2);
                             
    _msg.j1939_pid.Data[1] = pthis->group_num;
    _msg.j1939_pid.Data[2] = pthis->addr_num;
    _msg.j1939_pid.Data[3] = pthis->addr_info;
    _msg.j1939_pid.Data[4] = pthis->addr_info_end;
    _msg.j1939_pid.Data[5] = 0;
    _msg.j1939_pid.Data[6] = 0;
    _msg.j1939_pid.Data[7] = 0;

    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);
    return SUCCESS;
}


//功率控制模块心跳帧
int j1939_TICK_MSG_AOC(void)
{
    J1939_MESSAGE _msg;

    /*****发送数据(参考J1939的ID组成填充下面)***/
    _msg.j1939_pid.DataPage = 0;
    _msg.j1939_pid.Priority = J1939_PROPRIETARY_PRIORITY;
    _msg.j1939_pid.PDUSpecific = 0x9F; //PDU1格式下 -- 目标地址
    _msg.j1939_pid.DataLength = 8;     //数据长度
    _msg.j1939_pid.PDUFormat = 0x40;   //指定PDU格式 < 240为 PDU1
    _msg.j1939_pid.Data[0] = 0;        
    _msg.j1939_pid.Data[1] = 0;
    _msg.j1939_pid.Data[2] = 0;
    _msg.j1939_pid.Data[3] = 0;
    _msg.j1939_pid.Data[4] = 0;
    _msg.j1939_pid.Data[5] = 0;
    _msg.j1939_pid.Data[6] = 0;
    _msg.j1939_pid.Data[7] = 0;

    while (J1939_Send_Message( &_msg, Select_CAN_NODE_1) != RC_SUCCESS);
    return SUCCESS;
}


